import {
    NativeModules
} from 'react-native'

import JJAPPConfig from './../resource/file/appConfig/JJAPPConfig'
import {JJUtil} from '../util/index'
import {JJError} from '../bizUtil/index.js';

class JJRequestAgent
{
    static instance
    requestList = [];
    readyRequestList= []

    static sharedInstance() {
        if (false === this.instance instanceof this) {
            this.instance = new this;
        }
        return this.instance;
    }

    start(request) {
        if (this.__isPrefixRequest(request)){
            this.__start(request)
        } else {
            this.__startPrefixRequest(request)
        }
    }

    __isPrefixRequest(request) {
        return true
    }

    __startPrefixRequest(request) {
        // todo if have prefix request, add request to readyRequestList, when finish prefix request, invork __startReadyRequestList() 
    }

    __start(request) {
        this.addRequest(request);

        if (!request.isAllowBeginSendRequest()) {
            this.handleNetworkFailRequestResult(request, JJError.networkReuqestFailError)
            return
        }

        if (JJAPPConfig.isAppParasitifer()) {
            this.__startAppRequest(request)   
        } else if (JJAPPConfig.isH5Parasitifer()) {
            this.__startH5Request(request)
        }
    }

    __startAppRequest(request) {
        const paramters = request.requestParameterForRN();
        const JJRNBridge = NativeModules.JJRNBridge
        JJRNBridge.request(paramters).then((response) => {
            this.handleNetworkSuccessRequestResult(request, JSON.parse(response));
        }).catch((error) => {
            this.handleNetworkFailRequestResult(request, error);
        });
    }

    __startH5Request(request) {
        const url = request.buildRequestUrl()
        const header = request.getRequestHeader()
        const paramters = request.requestParameter()
        const method = request.methodType
        const credential = request.getRequestCredentials()

        const me = this
        window.fetch(url, {
            method: method,
            body: JSON.stringify(paramters),
            headers: header,
            //credentials: credential
        }).then((response) => {
            request.responseCode = response.status;
            request.responseHeader = response.headers;
            if (response.status >= 200 && response.status <= 299) {
                request.setResponseData(response).then((value) => {
                    request.responseData = value
                    me.handleNetworkSuccessRequestResult(request, value);
                })
            } else {
                me.handleNetworkFailRequestResult(request, response.data);
            }
        }).catch((error) => {
            me.handleNetworkFailRequestResult(request, error);
        })
    }

    stop(request) {
        request.cancelTimeoutTimer();
        this.removeRequest(request);
    }

    handleNetworkSuccessRequestResult(request, response) {
        request.cancelTimeoutTimer();

        const index = this.requestList.indexOf(request);
        if (index < 0) {
            return;
        }

        this.removeRequest(request);

        request.requestCompleteFilter(response).then((value) => {
            const isSuccess = request.successForBusiness(value)
            const result = request.filterSuccessCallBackValue(isSuccess, value);
            
            if (JJUtil.isNotNull(request.networkSuccessCallBack)) {
                request.networkSuccessCallBack(isSuccess, result, request.otherInfo);
            }

            if (request.isNeedPostResponseNotification) {
                request.postResponseNotification(isSuccess, result, null)
            }
        });
    }

    handleNetworkFailRequestResult(request, error) {
        request.cancelTimeoutTimer();

        const index = this.requestList.indexOf(request);
        if (index < 0) {
            return;
        }

        this.removeRequest(request);
        request.requestFailedFilter(error).then((value) => {
            const errorObj = request.filterFailCallBackValue(value)

            if (JJUtil.isNotNull(request.networkFailCallBack)) {   
                request.networkFailCallBack(errorObj, request.otherInfo);  
            }

            if (request.isNeedPostResponseNotification) {
                request.postResponseNotification(false, null, errorObj)
            }
        });
    }

    addRequest(request) {
        const index = this.requestList.indexOf(request);
        if (index >= 0) {
            return;
        }
        this.requestList.push(request);
    }

    removeRequest(request) {
        const index = this.requestList.indexOf(request);
        if (index >= 0) {
            this.requestList.splice(index, 1);
        }
    }

    addRequestToReadyRequestList(request) {
        const index = this.readyRequestList.indexOf(request);
        if (index >= 0) {
            return;
        }
        this.readyRequestList.push(request);
    }

    removeRequestToReadyRequestList(request) {
        const index = this.readyRequestList.indexOf(request);
        if (index >= 0) {
            this.readyRequestList.splice(index, 1);
        }
    }

    __startReadyRequestList() {
        const length = this.readyRequestList.length
        for (let i = 0; i < length; ++i) {
            const request = this.readyRequestList[i]
            if (JJUtil.isNotNull(request)) {
                this.__start(request)
            }
        }

        this.readyRequestList = []
    }
}

export default JJRequestAgent;
